package com.mygame.game_server.login;

import com.alibaba.fastjson.JSONObject;
import com.mygame.game_server.MysqlSessionFactory;
import com.mygame.game_server.async.AsyncOperationProcessor;
import com.mygame.game_server.async.IAsyncOperation;
import com.mygame.game_server.login.db.IUserDao;
import com.mygame.game_server.login.db.UserEntity;
import com.mygame.game_server.util.RedisUtil;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;

import java.util.function.Function;

/**
 * 登陆服务
 */
public final class LoginService {
    /**
     * 日志服务
     */
    static private final Logger LOGGER = LoggerFactory.getLogger(LoginService.class);

    /**
     * 单例对象
     */
    static private final LoginService _instance = new LoginService();

    /**
     * 私有化类默认构造器
     */
    private LoginService() {
    }

    /**
     * 获取单例对象
     *
     * @return LoginService
     */
    static public LoginService getInstance() {
        return _instance;
    }

    /**
     *  获取hash值，从Hashmap里面复制的，好像是为了让key高位和低位全部参与运算而使数据分布更均匀
     * @param key 入参
     * @return int
     */
    private  int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 8);
    }

    /**
     * 用户登陆
     *
     * @param userName 用户名
     * @param password 用户密码
     * @param callback 回调
     */
    public void userLogin(String userName, String password, Function<UserEntity, Void> callback) {
        if (null == userName ||
                null == password) {
            return;
        }

        // 创建实力
        AsyncGetUserEntity asyncOp = new AsyncGetUserEntity(userName, password) {

            @Override
            public int getBindId() {
                return hash(userName);
            }

            @Override
            public void doFinish() {
                if (null != callback) {

                    //重写dofinish，回调函数获取结果，真正执行传输实现逻辑
                    callback.apply(this.getUserEnentity());
                }
            }
        };

        //将任务交给异步线程处理,好复杂，好绕
        AsyncOperationProcessor.getInstance().process(asyncOp);

    }

    /**
     * 更新热地说中的数据
     * @param userEntity
     */
    private void updateBasicInfoInRedis(UserEntity userEntity) {
        if (null == userEntity) {
            return;
        }

        try (Jedis jedis = RedisUtil.getJedis()) {

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("userName",userEntity.userName);
            jsonObject.put("heroAvatar",userEntity.heroAvatar);
            jedis.hset("User_"+userEntity.userId,"BasicInfo", jsonObject.toJSONString());

        } catch (Exception ex) {
            LOGGER.error(ex.getMessage(),ex);
        }
    }

    private static class AsyncGetUserEntity implements IAsyncOperation {
        /**
         * 用户名称
         */
        private final String _userName;

        /**
         * 用户密码
         */
        private final String _password;

        /**
         * 用户实体
         */
        public UserEntity _userEnentity;

        public UserEntity getUserEnentity() {
            return _userEnentity;
        }

        public void setUserEnentity(UserEntity _userEnentity) {
            this._userEnentity = _userEnentity;
        }

        AsyncGetUserEntity(String userName, String password) {
            _userName = userName;
            _password = password;

        }

        @Override
        public void doAsync() {

            try (SqlSession mySqlSession = MysqlSessionFactory.openSession()) {
                // 获取 DAO   字节码生成 动态代理
                IUserDao dao = mySqlSession.getMapper(IUserDao.class);
                // 获取用户实体
                UserEntity userEntity = dao.getByUserName(_userName);

                LOGGER.info("当前线程 = {}", Thread.currentThread().getName());

                if (null != userEntity) {
                    if (!_password.equals(userEntity.password)) {
                        throw new RuntimeException("密码错误");
                    }
                } else {
                    userEntity = new UserEntity();
                    userEntity.userName = _userName;
                    userEntity.password = _password;
                    userEntity.heroAvatar = "Hero_Shaman";

                    dao.insertInto(userEntity);
                }
//                // CompletableFuture.allOf 这个线程池貌似也行
//                //回调函数获取结果，貌似是利用lambta延迟
//                if (null != _password) {
//                    callback.apply(userEntity);
//                }
                LoginService.getInstance().updateBasicInfoInRedis(userEntity);
                _userEnentity = userEntity;

            } catch (Exception ex) {
                // 记录错误日志
                LOGGER.error(ex.getMessage(), ex);

            }

        }


    }
}
